package com.sf.dlb.service;

import com.sf.dlb.constant.CacheConstant;
import com.sf.dlb.constant.ResponseConstant;
import com.sf.dlb.jpa.model.*;
import com.sf.dlb.jpa.repository.*;
import com.sf.dlb.mapper.dao.UserGradeMapper;
import com.sf.dlb.utils.*;
import com.sf.dlb.vo.ResultVO;
import com.sf.dlb.vo.UserGradeVO;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * Created by tanjing on 2019/5/7.
 */
@Service
public class UserGradeService extends BaseService{
    private Logger logger= LoggerFactory.getLogger(UserGradeService.class);
    @Autowired
    private UserGradeRepository userGradeRepository;
    @Autowired
    private UserGradeBuyRecordRepository userGradeRecordRepository;
    @Autowired
    private UserInfoRepository userInfoRepository;
    @Autowired
    private UserWalletRepository userWalletRepository;
    @Autowired
    private UserWalletService userWalletService;
    @Autowired
    private UserInvitationRepository userInvitationRepository;
    @Autowired
    private UserGradeMapper userGradeMapper;

    /**
     * 获取等级列表
     * @param userId
     * @return
     */
    public ResultVO gradeList(String userId){
        logger.info("gradeList start userId={}",userId);
        UserInfo userInfo=userInfoRepository.findByUserIdAndDelFlag(userId,"0");
        String userGrade=userInfo.getUserGrade();
        List<UserGradeInfo> userGradeInfo=userGradeRepository.findAll();
        List<UserGradeVO> userGradeVOS=new ArrayList<>();
        for (UserGradeInfo gradeInfo:userGradeInfo) {
            //普通用户等级不返回
            if(StringUtils.equals(gradeInfo.getGrade(),"0")){
                continue;
            }
            String grade=gradeInfo.getGrade();
            UserGradeVO userGradeVO=new UserGradeVO();
            BeanUtils.copyProperties(gradeInfo,userGradeVO);
            userGradeVO.setUpdateDate(gradeInfo.getUpdateDate().getTime());
            userGradeVO.setUserId(userId);
            String buyState=handlerBuyState(userGrade,grade);
            userGradeVO.setBuyState(buyState);
            Date overdueDate=DateUtils.addDays(new Date(),gradeInfo.getValidity());
            String validityFormat=DateUtils.formatDate(new Date(),"yyyy.MM.dd")+"至"+DateUtils.formatDate(overdueDate,"yyyy.MM.dd");
            userGradeVO.setValidityFormat(validityFormat);
            userGradeVOS.add(userGradeVO);
        }
        return ResultVOUtil.success(userGradeVOS);
    }
    /**
     * 获取等级列表(未登录)
     * @return
     */
    public ResultVO gradeList(){
        logger.info("gradeList start ");
        List<UserGradeInfo> userGradeInfo=userGradeRepository.findAll();
        List<UserGradeVO> userGradeVOS=new ArrayList<>();
        for (UserGradeInfo gradeInfo:userGradeInfo) {
            //普通用户等级不返回
            if(StringUtils.equals(gradeInfo.getGrade(),"0")){
                continue;
            }
            UserGradeVO userGradeVO=new UserGradeVO();
            BeanUtils.copyProperties(gradeInfo,userGradeVO);
            userGradeVO.setUpdateDate(gradeInfo.getUpdateDate().getTime());
            userGradeVO.setBuyState("1");//默认是购买
            Date overdueDate=DateUtils.addDays(new Date(),gradeInfo.getValidity());
            String validityFormat=DateUtils.formatDate(new Date(),"yyyy.MM.dd")+"至"+DateUtils.formatDate(overdueDate,"yyyy.MM.dd");
            userGradeVO.setValidityFormat(validityFormat);
            userGradeVOS.add(userGradeVO);
        }
        return ResultVOUtil.success(userGradeVOS);
    }
    /**
     * 处理购买-过期时间
     * @param buyState 购买状态
     * @param userId
     * @param gradeValidityTime
     * @param beforeGrade
     * @param gradeInfo 要购买等级的信息
     * @return Date
     */
    @Transactional
    public Date handlerOverdueTime(String buyState,String userId,Date gradeValidityTime,String beforeGrade,UserGradeInfo gradeInfo){
        logger.info("handlerOverdueTime buyState={},userId={},gradeValidityTime={},beforeGrade={},gradeInfo={}",buyState,userId,gradeValidityTime,beforeGrade,GsonUtils.getInstance().toJson(gradeInfo));
        Date currentDate=new Date();
        Date overdueDate;
        Integer validity=gradeInfo.getValidity();
        if(StringUtils.equals(buyState,"2")){ //购买状态,2=续费,续费是再原来的结束时间继续追加时间
            overdueDate=DateUtils.addDays(gradeValidityTime,validity);
        }else{
            int higherDay=buyHigherGradeCount(userId,beforeGrade,gradeValidityTime,gradeInfo.getGrade());
            int validityDay=validity+higherDay;
            overdueDate=DateUtils.addDays(currentDate,validityDay);
        }
        logger.info("handlerOverdueTime overdueDate={},",overdueDate);
        return overdueDate;
    }
    /**
     * 处理购买-状态
     * @param userGrade 用户当前等级
     * @param grade 列表条目的等级
     * @return
     */
    public String handlerBuyState(String userGrade,String grade){
//        购买状态(0=不可用 1=购买 2=续费 3=购买高级)
        logger.info("handlerBuyState userGrade={},grade={}",userGrade,grade);
        int userGradeI=Integer.parseInt(userGrade);
        int gradeI=Integer.parseInt(grade);
        String stateValue="";
        //普通用户
        if(userGradeI==0){
            stateValue="1";
        }else{
            //已经购买了等级
            if(userGradeI==gradeI){//相等当前等级，当前等级=续费
                stateValue="2";
            }else if(userGradeI>gradeI){//大于当前等级，当前等级=不可用
                stateValue="0";
            }else if(userGradeI<gradeI){//小于当前等级，当前等级=购买高级
                stateValue="3";
            }
        }
        logger.info("handlerBuyState stateValue={}",stateValue);
        return stateValue;
    }
    /**
     * 获取等级信息
     * @param grade
     * @return
     */
    public ResultVO gradeInfo(String userId,String grade){
        logger.info("gradeInfo start userId={},grade={}",userId,grade);
        UserGradeInfo userGradeInfo;
        UserInfo userInfo=null;
        UserGradeVO userGradeVO=new UserGradeVO();
        //查询当前用户等级信息
        if(StringUtils.isEmpty(grade)){
            userInfo=userInfoRepository.findByUserIdAndDelFlag(userId,"0");
            grade=userInfo.getUserGrade();
        }
        userGradeInfo =userGradeRepository.findByGradeAndDelFlag(grade,"0");
        if(null==userGradeInfo){
            logger.info("无此等级信息");
            return ResultVOUtil.error(ResponseConstant.ERROR,"无此等级信息");
        }
        BeanUtils.copyProperties(userGradeInfo,userGradeVO);
        userGradeVO.setUpdateDate(userGradeInfo.getUpdateDate().getTime());
        if(null!=userInfo){
            String userGrade=userInfo.getUserGrade();
            userGradeVO.setUserId(userId);
            userGradeVO.setValidityEndDate((null==userInfo.getGradeValidityTime())?0L:userInfo.getGradeValidityTime().getTime());
            String buyState=handlerBuyState(userGrade,grade);
            userGradeVO.setBuyState(buyState);
            Date overdueDate=DateUtils.addDays(new Date(),userGradeInfo.getValidity());
            String validityFormat=DateUtils.formatDate(new Date(),"yyyy.MM.dd")+"至"+DateUtils.formatDate(overdueDate,"yyyy.MM.dd");
            userGradeVO.setValidityFormat(validityFormat);
        }
        return ResultVOUtil.success(userGradeVO);
    }
    /**
     * 购买等级
     * @param userId 购买用户id
     * @param gradeId 等级id
     * @return
     */
    @Transactional
    public ResultVO buyGrade(String userId,Long gradeId,String payPassword){
        logger.info("==buyGrade start userId={},gradeId={}",userId,gradeId);
//        1》事务，并发问题；
        String key= CacheConstant.USER_CACHE+CacheConstant.USER_BUY_GRADE_CONCURRENT_PREFIX+userId+":"+gradeId;
        boolean isconcurrentFalg=isConcurrent(key);
        if(isconcurrentFalg){
            return ResultVOUtil.error(ResponseConstant.ERROR,"不能重复购买");
        }
        UserInfo userInfo=userInfoRepository.findByUserIdAndDelFlag(userId,"0");
        if(null==userInfo){
            return ResultVOUtil.error(ResponseConstant.ERROR,"暂无用户信息");
        }
        //支付密码是否正确
        boolean payPasswordFlag=StringUtils.isBlank(userInfo.getPayPassword())?false:SecurityUtils.validatePassword(payPassword,userInfo.getPayPassword());
        if(!payPasswordFlag){
            return ResultVOUtil.error(ResponseConstant.ERROR_GRADE_PAY_PASSWORD,"支付密码错误");
        }
        //1》判断是否可以购买
        UserGradeInfo userGradeInfo=userGradeRepository.findById(gradeId);
        if(null==userGradeInfo){
            return ResultVOUtil.error(ResponseConstant.ERROR,"暂无等级信息");
        }
        if(StringUtils.equals(userGradeInfo.getGrade(),"0")){
            return ResultVOUtil.error(ResponseConstant.ERROR,"不能购买此等级");
        }
        String buyState=handlerBuyState(userInfo.getUserGrade(),userGradeInfo.getGrade());
        if(StringUtils.equals(buyState,"0")){
            return ResultVOUtil.error(ResponseConstant.ERROR,"不能购买低等级");
        }
//      2》判断dlb是否足够；
        UserWalletInfo userWalletInfo = userWalletRepository.findByUserIdAndDelFlag(userId,"0");
        if(null==userWalletInfo){
            return ResultVOUtil.error(ResponseConstant.ERROR,"暂无用户钱包信息");
        }
        Double gradlePrice=userGradeInfo.getPrice();
        Double lockDlb=userWalletInfo.getLockDlb();
        logger.info("buyGrade gradlePrice={},lockDlb={}",gradlePrice,lockDlb);
        if(lockDlb<gradlePrice){
            return ResultVOUtil.error(ResponseConstant.ERROR_GRADE_BALANCE_INSUFFICIENT,"您的锁仓数量不足,快去充值吧");
        }
//        2》购买-》续费，购买更高级
        handlerBuy(buyState,userInfo,userGradeInfo,userWalletInfo);
        // 返回VO
        Map resultMapVo=new HashMap();
        String validityFormat=DateUtils.formatDate(new Date(),"yyyy年MM月dd日")+" 至 "+DateUtils.formatDate(userInfo.getGradeValidityTime(),"yyyy年MM月dd日");
        resultMapVo.put("validityFormat",validityFormat);
        logger.info("== buyGrade end ");
        return ResultVOUtil.success(resultMapVo);
    }

    /**
     * 处理购买
     * @param buyState 购买状态
     * @param userInfo 购买用户
     * @param userGradeInfo 用户购买的等级
     * @param userWalletInfo 用户钱包
     */
    @Transactional
    public void handlerBuy(String buyState,UserInfo userInfo,UserGradeInfo userGradeInfo,UserWalletInfo userWalletInfo){
        logger.info("== handlerBuy  buyState={}，UserInfo={},userGradeInfo={},userWalletInfo={}"
                ,buyState
                ,GsonUtils.getInstance().toJson(userInfo)
                ,GsonUtils.getInstance().toJson(userGradeInfo)
                ,GsonUtils.getInstance().toJson(userWalletInfo));
        String grade=userGradeInfo.getGrade();
        Double price=userGradeInfo.getPrice();
        String userId=userInfo.getUserId();
        String beforeGrade=userInfo.getUserGrade();
        Date gradeValidityTime=userInfo.getGradeValidityTime();
        Date overdueDate=handlerOverdueTime(buyState,userId,gradeValidityTime,beforeGrade,userGradeInfo);
        Integer validityDay=(int)(DateUtils.differDay(new Date(),overdueDate));
        //5》阅读倍数增加；*
//            》通过user_grade表就可以查询出阅读倍数增加
        //6》分配邀请码；* -》逻辑取消
//        7》购买抽成； *
        buyGradDivide(userId,userGradeInfo);
//        1》会员等级更新；有效期更新； *
        userInfo.setUserGrade(grade);
        userInfo.setGradeValidityTime(overdueDate);
        userInfo.setUpdateDate(new Date());
        userInfoRepository.save(userInfo);
//        2》添加购买记录；*
        UserGradeBuyRecordInfo userGradeBuyRecordInfo=new UserGradeBuyRecordInfo();
        userGradeBuyRecordInfo.setUserId(userId);
        userGradeBuyRecordInfo.setBeforeGrade(beforeGrade);
        userGradeBuyRecordInfo.setGrade(grade);
        userGradeBuyRecordInfo.setValidity(validityDay);
        userGradeBuyRecordInfo.setValidityTime(overdueDate);
        userGradeBuyRecordInfo.setPayPrice(price);
        userGradeBuyRecordInfo.setBuyType(buyState);
        userGradeBuyRecordInfo.setUpdateDate(new Date());
        userGradeBuyRecordInfo.setCreateDate(new Date());
        userGradeBuyRecordInfo=userGradeRecordRepository.save(userGradeBuyRecordInfo);
        //3》dlb减少；*
        //4》dlb流水记录；* @TODO (来源类型)
        String source=ResponseConstant.source_type_buy_grade;
        String sourceDesc=ResponseConstant.source_type_buy_grade_value+":购买记录id:"+userGradeBuyRecordInfo.getId();
        userWalletService.userWalletLockDlbSub(userId,price,source,sourceDesc);
        logger.info("== handlerBuy  end");
    }
    /**
     * 购买抽成
     * @param  useUserId  当前购买用户id
     * @param  currntUserGradeInfo 当前购买用户等级信息
     */
    @Transactional
    public void buyGradDivide(String useUserId,UserGradeInfo currntUserGradeInfo){
        logger.info("== buyGradDivide useUserId={},currntUserGradeInfo={}",useUserId,GsonUtils.getInstance().toJson(currntUserGradeInfo));
        Integer currentUserGradeI=Integer.parseInt(currntUserGradeInfo.getGrade());
        double currntPrice=currntUserGradeInfo.getPrice();
        double currntbuyDivide=Arith.div(currntUserGradeInfo.getBuyDivide(),100);//获取分成百分比
        //1,抽成给谁；谁邀请的；@TODO 历史数据
        UserInvitationInfo userInvitationInfo=userInvitationRepository.findByInvitationUserIdAndDelFlag(useUserId,"0");
        if(null==userInvitationInfo){
            logger.info("buyGradDivide 此用户不是被邀请的");
            return;
        }
        String ownerUserId=userInvitationInfo.getUserId();
        if(StringUtils.equals(ownerUserId,"系统公测")){
            logger.info("buyGradDivide 此用户是公测用户");
            return;
        }
        UserInfo ownerUserInfo=userInfoRepository.findByUserIdAndDelFlag(ownerUserId,"0");
        //2，邀请人的等级
        Integer ownerUserGradeI=Integer.parseInt(ownerUserInfo.getUserGrade());
        if(ownerUserGradeI==0){
            logger.info("buyGradDivide ownerUserGrade==0 普通用户无法享受购买分成");
            return;
        }
        //3.分成记录是否上限
        boolean limitFlag=isInvitationDivideLimit(useUserId,ownerUserInfo);
        logger.info("buyGradDivide 抽成记录是否上限 limitFlag={}",limitFlag);
        if(limitFlag){
            return;
        }
        //抽成多少；
        double divideNumber;
        if(ownerUserGradeI>=currentUserGradeI){
            logger.info("buyGradDivide 邀请者等级大于当前用户购买等级 ownerUserGradeI={},currentUserGradeI={}",ownerUserGradeI,currentUserGradeI);
            divideNumber=Arith.mul(currntPrice,currntbuyDivide);
        }else{
            logger.info("buyGradDivide 邀请者等级小于当前用户购买等级 ownerUserGradeI={},currentUserGradeI={}",ownerUserGradeI,currentUserGradeI);
            UserGradeInfo ownerUserGradeInfo=userGradeRepository.findByGradeAndDelFlag(ownerUserInfo.getUserGrade(),"0");
            double buyDividePercent=Arith.div(ownerUserGradeInfo.getBuyDivide(),100);//分成百分比
            divideNumber=Arith.mul(ownerUserGradeInfo.getPrice(),buyDividePercent);
        }
        logger.info("buyGradDivide divideNumber={}",divideNumber);
        //3，把分成的奖励分配给指定用户@TODO(来源类型)
        //3.1 更新用户钱包
        //3.2 更新dlb流水
        String source=ResponseConstant.source_type_buy_grade_divide;
        String sourceDesc=ResponseConstant.source_type_buy_grade_divide_value +":购买用户:"+useUserId;
        userWalletService.updateUserWallet(ownerUserInfo.getUserId(),divideNumber,source,sourceDesc);
        logger.info("buyGradDivide end");
    }
    /**
     * 抽成记录是否上限
     *
     */
    @Transactional
    public boolean isInvitationDivideLimit(String useUserId,UserInfo ownerUserInfo){
        logger.info("isInvitationDivideLimit useUserId={},ownerUserInfo={}",useUserId,GsonUtils.getInstance().toJson(ownerUserInfo));
        UserGradeInfo userGradeInfo=userGradeRepository.findByGradeAndDelFlag(ownerUserInfo.getUserGrade(),"0");
        Integer invitationNumber=userGradeInfo.getInvitationNumber();
        List<String> list=userGradeMapper.queryUserBuy(ownerUserInfo.getUserId(),invitationNumber);
        logger.info("isInvitationDivideLimit invitationNumber={},list.size={}",invitationNumber,list.size());
        //没有购买者
        if(CollectionUtils.isEmpty(list)||list.size()==0){
            return false;
        }
        boolean returnFlag=true;
        if(list.size()<invitationNumber){
            returnFlag=false;
        }else if(list.size()==invitationNumber){
            for (String invitationUserId:list) {
                //在范围之内
                if(StringUtils.equals(invitationUserId,useUserId)){
                    returnFlag=false;
                    break;
                }
            }
        }
        return returnFlag;
    }
    /**
     * 购买高等级，有效期天数折算
     * @param userId
     * @param validityTime
     * @param currentGrade  用户当前等级
     * @param heiherGrade   用户购买的高等级
     */
    @Transactional
    public int buyHigherGradeCount(String userId,String currentGrade,Date validityTime,String heiherGrade){
        logger.info("buyHigherGradeCount userId={},currentGrade={},heiherGrade={}",userId,currentGrade,heiherGrade);
        if(StringUtils.equals(currentGrade,"0")){
            logger.info(" buyHigherGradeCount 普通等级 ");
            return 0;
        }
        if(StringUtils.equals(currentGrade,heiherGrade)){
            logger.info(" buyHigherGradeCount 购买的相同等级 ");
            return 0;
        }
        int currentGradeI=Integer.parseInt(currentGrade);
        int heiherGradeI=Integer.parseInt(heiherGrade);
        if(heiherGradeI<currentGradeI){
            logger.info(" buyHigherGradeCount 购买等级小于当前等级 ");
            return 0;
        }
        //得到等级对应到每天的dlb单价
        UserGradeInfo currentUserGradeInfo=userGradeRepository.findByGradeAndDelFlag(currentGrade,"0");
        Double currentGradePrice=currentUserGradeInfo.getPrice();
        Integer currentGradeValidity=currentUserGradeInfo.getValidity();
        double everyCurrentGrade=Arith.div(currentGradePrice,currentGradeValidity); //当前等级单价
        UserGradeInfo heiherUserGradeInfo=userGradeRepository.findByGradeAndDelFlag(heiherGrade,"0");
        Double heiherGradePrice=heiherUserGradeInfo.getPrice();
        Integer heiherGradeValidity=heiherUserGradeInfo.getValidity();
        double everyHeiherGradePrice=Arith.div(heiherGradePrice,heiherGradeValidity);//要购买等级的单价
        logger.info("dlb单价 everyCurrentGrade={},everyHeiherGradePrice={}",everyCurrentGrade,everyHeiherGradePrice);
        //当前等级未消费的天数
        double currentGradeDay=DateUtils.differDay(new Date(),validityTime);
        int currentGradeDayI=(int)currentGradeDay;
        //未消费的dlb
        double notUseDlb=Arith.mul(everyCurrentGrade,currentGradeDayI);
        logger.info("消费的天数 currentGradeDayI={},notUseDlb={}",currentGradeDayI,notUseDlb);
        //折算高等级的天数
        double heiherGradeDay=Arith.div(notUseDlb,everyHeiherGradePrice);
        int heiherGradeDayI=(int)heiherGradeDay;
        logger.info("折算高等级的天数 heiherGradeDayI={}",heiherGradeDayI);
        return heiherGradeDayI;
    }
}
